package com.fvff.sanctuary.model;

import com.fvff.sanctuary.model.embeddable.Rating;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.CollectionOfElements;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * MediaItem
 */
@Entity(name = "MEDIA_ITEM")
public final class MediaItem implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "MEDIA_ITEM_ID")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "ALBUM_ID")
    private Album album;

    @Column(name = "OPEN_SOCIAL_ALBUM_ID")
    private String openSocialAlbumId;

    @Column(name = "CREATED")
    private Date created;

    @Column(name = "DESCRIPTION")
    private String description;

    @Column(name = "DURATION")
    private Integer duration;   // In Seconds

    @Column(name = "FILE_SIZE")
    private Long fileSize;      // In Bytes

    @Column(name = "OPEN_SOCIAL_ID")
    private String openSocialId;

    @Column(name = "LANGUAGE")
    private String language;    // In ISO 639-3

    @Column(name = "LAST_UPDATED")
    private Date lastUpdated;

    @ManyToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
    @JoinColumn(name = "LOCATION_ID")
    private Address location;

    @Column(name = "MIME_TYPE")
    private String mimeType;

    @Column(name = "VIEWS")
    private Integer views;

    @Column(name = "COMMENTS_COUNT")
    private Integer commentsCount;

    @Column(name = "VOTES")
    private Integer votes;

    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "value", column = @Column(name = "RATING"))
    })
    private Rating rating;

    @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
    @JoinTable(name = "MEDIA_ITEM_TAGGED_PERSON",
            joinColumns = @JoinColumn(name = "MEDIA_ITEM_ID"),
            inverseJoinColumns = @JoinColumn(name = "PERSON_ID"))
    private Set<Person> taggedPersons = new HashSet<Person>();

    @Column(name = "TAGS")
    @CollectionOfElements
    private Set<String> tags = new HashSet<String>();

    @ManyToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
    @JoinColumn(name = "THUMBNAIL_URL_ID")
    private Url thumbnailUrl;

    @Column(name = "TITLE")
    private String title;

    @Column(name = "MEDIA_ITEM_TYPE")
    @Enumerated(EnumType.STRING)
    private MediaItemType mediaItemType;

    @ManyToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
    @JoinColumn(name = "URL_ID")
    private Url Url;

    public Long getId() {
        return id;
    }

    public void setId(final Long id) {
        this.id = id;
    }

    public Album getAlbum() {
        return album;
    }

    public void setAlbum(final Album album) {
        this.album = album;
    }

    public String getOpenSocialAlbumId() {
        return openSocialAlbumId;
    }

    public void setOpenSocialAlbumId(final String openSocialAlbumId) {
        this.openSocialAlbumId = openSocialAlbumId;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(final Date created) {
        this.created = created;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    public Integer getDuration() {
        return duration;
    }

    public void setDuration(final Integer duration) {
        this.duration = duration;
    }

    public Long getFileSize() {
        return fileSize;
    }

    public void setFileSize(final Long fileSize) {
        this.fileSize = fileSize;
    }

    public String getOpenSocialId() {
        return openSocialId;
    }

    public void setOpenSocialId(final String openSocialId) {
        this.openSocialId = openSocialId;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(final String language) {
        this.language = language;
    }

    public Date getLastUpdated() {
        return lastUpdated;
    }

    public void setLastUpdated(final Date lastUpdated) {
        this.lastUpdated = lastUpdated;
    }

    public Address getLocation() {
        return location;
    }

    public void setLocation(final Address location) {
        this.location = location;
    }

    public String getMimeType() {
        return mimeType;
    }

    public void setMimeType(final String mimeType) {
        this.mimeType = mimeType;
    }

    public Integer getViews() {
        return views;
    }

    public void setViews(final Integer views) {
        this.views = views;
    }

    public Integer getCommentsCount() {
        return commentsCount;
    }

    public void setCommentsCount(final Integer commentsCount) {
        this.commentsCount = commentsCount;
    }

    public Integer getVotes() {
        return votes;
    }

    public void setVotes(final Integer votes) {
        this.votes = votes;
    }

    public Rating getRating() {
        return rating;
    }

    public void setRating(final Rating rating) {
        this.rating = rating;
    }

    public Set<Person> getTaggedPersons() {
        return taggedPersons;
    }

    public void setTaggedPersons(final Set<Person> taggedPersons) {
        this.taggedPersons = taggedPersons;
    }

    public Set<String> getTags() {
        return tags;
    }

    public void setTags(final Set<String> tags) {
        this.tags = tags;
    }

    public Url getThumbnailUrl() {
        return thumbnailUrl;
    }

    public void setThumbnailUrl(final Url thumbnailUrl) {
        this.thumbnailUrl = thumbnailUrl;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(final String title) {
        this.title = title;
    }

    public MediaItemType getMediaItemType() {
        return mediaItemType;
    }

    public void setMediaItemType(final MediaItemType mediaItemType) {
        this.mediaItemType = mediaItemType;
    }

    public Url getUrl() {
        return Url;
    }

    public void setUrl(final Url url) {
        Url = url;
    }

    @Override
    public boolean equals(final Object o) {
        return o != null && (o == this || o.getClass() == getClass() && EqualsBuilder.reflectionEquals(this, o));
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).
                append("something", id).
                toString();
    }
}
